import { FileInfo, FileUploadConfig, FileUploadListener } from "../FileServerClient";
import UUID from "../../../common/UUID";
import Beans from "../../../common/utils";
import Logger from "../../../log/Logger";
import AbstractXMLHttpClient from "./AbstractXMLHttpClient";
import Fetch from "./Fetch";


/**
 *  Note: (1. 可获取上传文件的大小)
 *  ReactNativeXMLHttp  文件上传客户端.
 *  适用SDK 平台: ReactNative(Android, ios)
 *  配置方式
 sdkConfig.fileServerConfig = {
        use: 'aliyun',
        // use: 'local',
        client: 'rn-xmlhttp',
        baseUrl: 'http://192.168.0.100:8082',
        version: 'v1',
    };
 *
 * */

class FileBlobData {
    blobId: string|any;
    lastModified: number|any;
    name: string|any;
    offset: number|any;
    size: number|any;// 文件大小(字节)
    type: string|any;// mime type
}

export default class ReactNativeXMLHttpClient extends AbstractXMLHttpClient{
    init(uploadConfig: FileUploadConfig, listeners: FileUploadListener | undefined): void {
        const self = this;
        self.uploadConfig = uploadConfig;
        if(listeners !== undefined){
            this.beforeUploadCallback = listeners.beforeUploadCallback;
            this.progressCallback = listeners.progressCallback;
            this.uploadedCallback = listeners.uploadedCallback;
            this.errorCallback = listeners.errorCallback;
        }
    }

    public upload(path:string):string{
        const self = this;
        // 触发用户额外自定义的 beforeUploadCallback 事件
        let fileInfo = new FileInfo();
        if(!path){
            this.setErrorCallback(603, '文件路径为空');
            return "";
        }
        const filename = path.substring(path.lastIndexOf("/")+1);
        if(!filename){
            this.setErrorCallback(604, '无法获取文件名:' + filename);
            return "";
        }

        fileInfo.id = UUID.gen();
        fileInfo.name = filename;
        fileInfo.originFileName = filename;
        fileInfo.size = 0; // 使用fetchSourceFileInfo计算
        fileInfo.type = self.getFileType(filename); // 若为空, 通过后缀名确认文件类型

        self.fetchSourceFileInfo(path).then((resp:FileBlobData)=>{
            fileInfo.size = parseInt(resp.size/1024+''); // 字节转kb
            if(typeof self.beforeUploadCallback === 'function'){
                const info = self.beforeUploadCallback(fileInfo);
                if(info){
                    self.fileInfo = info;
                }
                else {
                    self.fileInfo = fileInfo;
                }
            }
            else {
                self.fileInfo = fileInfo;
            }
            self.buildFormParams(fileInfo, function (host, formData) {
                self.applyReactNativeXMLHttpUploadDo(path, host, formData);
            });
        }).catch((e)=>{
            self.setErrorCallback(605, '无法获取文件大小:' + e);
        });



        return fileInfo.id;
    }

    // 使用 file:// 协议获取更多的信息
    private fetchSourceFileInfo(filePath:string):Promise<FileBlobData>{
        const fetch = Fetch.getFetchToolkit();
        const request: any = {method: 'HEAD'};
        return fetch(`file://${filePath}` as string, request).then(res =>{
            const fileMoreInfo =  (res._bodyBlob !== undefined && res._bodyBlob._data !== undefined) ? res._bodyBlob._data : undefined;
            if(fileMoreInfo === undefined){
                return Promise.reject('获取上传源文件' + filePath + '信息失败');
            }
            return Promise.resolve(fileMoreInfo);
        });
    }

    private applyReactNativeXMLHttpUploadDo(filePath, host, formParams:any):void {
        const self = this;
        if(!self.signInfo || !self.fileInfo){
            return;
        }
        let uploadUrl = '';
        if(this.serverConfig.use === 'local'){
            uploadUrl = (self.serverConfig.baseUrl + '/' + self.serverConfig.version + '/' + 'common/file/upload');
        }
        else if(this.serverConfig.use === 'aliyun'){
            uploadUrl = host;
        }
        let formData = new FormData();
        for(const v in formParams){
            formData.append(v, formParams[v]);
        }
        // use FILE PROTOCOL access the file
        let file = {
            uri: 'file://' + filePath,
            type: self.getMimeType(self.fileInfo.originFileName),
            name: self.fileInfo.originFileName
        };
        formData.append("file", file as any);

        // 开启XMLHttpRequest服务
        let xhr = new XMLHttpRequest();
        // 上传到文件服务器的地址
        let url = uploadUrl;
        // 开启post上传
        xhr.open('POST',url);
        xhr.setRequestHeader("Content-Type","multipart/form-data");// 七牛不用
        // 如果正在上传,返回上传进度
        if (xhr.upload){
            xhr.upload.onprogress = (evt)=>{
                const percent = (evt.loaded / evt.total).toFixed(2);
                // 显示进度条
                if(typeof self.progressCallback === 'function' && self.fileInfo){
                    self.fileInfo.uploadPercent = parseFloat(percent) * 100;
                    self.progressCallback(self.fileInfo);
                }
            }
        }
        xhr.onload = function () {
            if(self.serverConfig.use === 'local'){
                self.handleLocalServerResponse(xhr);
            }
            else if(self.serverConfig.use === 'aliyun'){
                self.handleAliyunServerResponse(xhr);
            }
        };
        Logger.info(`ready to post:${url} with params:${Beans.json(formData)}`);
        // 发送请求
        xhr.send(formData);
    };


}
